#include "stdafx.h"
#include "Z80_CPU.h"
#include "Manager.h"

int OpCodeCycles[] = {
//  0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
    1, 3, 2, 2, 1, 1, 2, 1, 5, 2, 2, 2, 1, 1, 2, 1,  // 0
    1, 3, 2, 2, 1, 1, 2, 1, 3, 2, 2, 2, 1, 1, 2, 1,  // 1
    2, 3, 2, 2, 1, 1, 2, 1, 2, 2, 2, 2, 1, 1, 2, 1,  // 2
    2, 3, 2, 2, 3, 3, 3, 1, 2, 2, 2, 2, 1, 1, 2, 1,  // 3
    1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1,  // 4
    1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1,  // 5
    1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1,  // 6
    2, 2, 2, 2, 2, 2, 1, 2, 1, 1, 1, 1, 1, 1, 2, 1,  // 7
    1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1,  // 8
    1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1,  // 9
    1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1,  // a
    1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1,  // b
    2, 3, 3, 4, 3, 4, 2, 4, 2, 4, 3, 2, 3, 6, 2, 4,  // c
    2, 3, 3, 1, 3, 4, 2, 4, 2, 4, 3, 1, 3, 1, 2, 4,  // d
    3, 3, 2, 1, 1, 4, 2, 4, 4, 1, 4, 1, 1, 1, 2, 4,  // e
    3, 3, 2, 1, 1, 4, 2, 4, 3, 2, 4, 1, 0, 1, 2, 4   // f
};

int OpCodeCyclesCB[] = {
//  0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f   
    2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2,  // 0
    2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2,  // 1
    2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2,  // 2
    2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2,  // 3
    2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2,  // 4
    2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2,  // 5
    2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2,  // 6
    2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2,  // 7
    2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2,  // 8
    2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2,  // 9
    2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2,  // a
    2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2,  // b
    2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2,  // c
    2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2,  // d
    2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2,  // e
    2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2   // f
};
u8 ZeroTable[256] = {
  0x80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0
};

Z80_CPU::Z80_CPU(void)
{
	this->reset();
}

Z80_CPU::~Z80_CPU(void)
{
}
int Z80_CPU::test(int b1, int b0) {
	BoyRegister tmp;
	tmp.B.B0 = b0;
	tmp.B.B1 = b1;
	return tmp.W;
}
void Z80_CPU::reset() {
			PC = 0;
			BC.B.B0 = 0;
			BC.B.B1 = 0;
			BC.W = 0;
			HL.B.B0 = 0;
			HL.B.B1 = 0;
			HL.W = 0;
			DE.B.B0 = 0;
			DE.B.B1 = 0;
			DE.W = 0;
			SP.B.B0 = 0;
			SP.B.B1 = 0;
			SP.W = 0;
			AF.B.B0 = 0;
			AF.B.B1 = 0;
			AF.W = 0;
                        /*flag_sign = false;
			flag_zero = false;
			flag_halfcarry = false;
			flag_parity = false;
			flag_overflow = false;
			flag_negative = false;
                        flag_carry = false;*/
		}
bool Z80_CPU::interpret() {
	u8 OpCode = this->man->mem->Read_memory_8(PC);
	if (OpCodeCycles[(int)OpCode] < this->man->CpuCycles) {
		PC++;
		switch(OpCode) {
                case 0x00:
				// NOP
				break;
                case 0x01:
				// LD BC, nnnn
				BC.B.B0 = this->man->mem->Read_memory_8(PC);
				PC++;
				BC.B.B1 = this->man->mem->Read_memory_8(PC);
				PC++;
				break;
                case 0x02:
				// LD (BC),A
				this->man->mem->Write_memory_8(BC.B.B0,AF.B.B0);
				break;
                case 0x06:
				// LD B,nn
				BC.B.B1 = this->man->mem->Read_memory_8(PC);
				PC++;
				break;
                case 0x08:
				// LD (NNNN), SP
				tmp_register.B.B0 = this->man->mem->Read_memory_8(PC);
				PC++;
				tmp_register.B.B1 = this->man->mem->Read_memory_8(PC);
				PC++;
				this->man->mem->Write_memory_8(tmp_register.W++,SP.B.B0);
				this->man->mem->Write_memory_8(tmp_register.W,SP.B.B1);
				break;
                case 0x0A:
				// LD A, (BC)
				AF.B.B1 = this->man->mem->Read_memory_8(BC.W);
				break;
                case 0x0E:
				// LD C,nn
				BC.B.B0 = this->man->mem->Read_memory_8(PC);
				PC++;
				break;
                case 0x11:
				//LD DE,nn
				DE.B.B0 = this->man->mem->Read_memory_8(PC);
				PC++;
				DE.B.B1 = this->man->mem->Read_memory_8(PC);
				PC++;
                case 0x12:
                                // LD (DE),A
                                this->man->mem->Write_memory_8(DE.W,AF.B.B1);
                case 0x13:
                                //INC DE
                                DE.W++;
                case 0x14:
                                //INC D
                                DE.B.B1++;
                                AF.B.B0 = (AF.B.B0 & C_FLAG)|ZeroTable[DE.B.B1]| (DE.B.B1&0x0F? 0:H_FLAG);
                case 0x15:

			default:
				// Unknown OpCode :'(
				break;
		}
		this->man->CpuCycles -= OpCodeCycles[OpCode];
		return true;
	}
	else {
		// Interrupts
		return false;
	}
}
